﻿using System.Collections.Generic;
using System.Windows.Media;
using Direct2D;
using Microsoft.WindowsAPICodePack.DirectX.Direct2D1;
using Microsoft.WindowsAPICodePack.DirectX.DirectWrite;
using SpectrumAnalyser.Controls.Wpf.ViewModels;
using SolidColorBrush = Microsoft.WindowsAPICodePack.DirectX.Direct2D1.SolidColorBrush;

namespace SpectrumAnalyser.CustomControls.Wpf.Direct2D
{
    public class Peaks2DScene: AnimatedScene
    {
        private IDictionary<Color, SolidColorBrush> _brushes;
        private SolidColorBrush _blackBrush;
        private SolidColorBrush _redBrush;
        private TextFormat _textFormat;
        private readonly DWriteFactory _writeFactory;

        private IList<SpectrumDataPointViewModel> _calculatePoints = new List<SpectrumDataPointViewModel>();

        public IList<SpectrumDataPointViewModel> Peaks
        {
            get { return _calculatePoints; }
            set { _calculatePoints = value; }
        }

        public IList<Color> Colors { get; set; }

        public Peaks2DScene()
            : base(100) // Will probably only be about 67 fps due to the limitations of the timer
        {
            _writeFactory = DWriteFactory.CreateFactory();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _writeFactory.Dispose();
            }
            base.Dispose(disposing);
        }

        protected override void OnCreateResources()
        {
            // We don't need to free any resources because the base class will
            // call OnFreeResources if necessary before calling this method.

            _brushes = new Dictionary<Color, SolidColorBrush>();
            if (Colors != null)
            {
                foreach (var source in Colors)
                {
                    _brushes.Add(source,
                                 RenderTarget.CreateSolidColorBrush(
                                     new ColorF(new ColorI(source.R, source.G, source.B))));
                }
            }

            _blackBrush = RenderTarget.CreateSolidColorBrush(new ColorF(0,0,0));
            _redBrush = RenderTarget.CreateSolidColorBrush(new ColorF(1,0,0));

            _textFormat = _writeFactory.CreateTextFormat("Arial", 10);

            base.OnCreateResources(); // Call this last to start the animation
        }

        protected override void OnFreeResources()
        {
            base.OnFreeResources(); // Call this first to stop the animation

            if (_brushes != null)
            {
                foreach (var solidColorBrush in _brushes)
                {
                    solidColorBrush.Value.Dispose();
                }
                _brushes = null;
            }
            if (_blackBrush != null)
            {
                _blackBrush.Dispose();
                _blackBrush = null;
            }if (_redBrush != null)
            {
                _redBrush.Dispose();
                _redBrush = null;
            }
            if (_textFormat != null)
            {
                _textFormat.Dispose();
                _textFormat = null;
            }
        }

        protected override void OnRender()
        {
            // This draws the ellipse in red on a semi-transparent blue background
            RenderTarget.BeginDraw();
            RenderTarget.Clear(new ColorF(0, 0, 0, 0));

            foreach (var calculatePoint in _calculatePoints)
            {
                var textlayout = _writeFactory.CreateTextLayout(calculatePoint.LabelText, _textFormat, 100, 200);
                var textPoint = new Point2F((float) calculatePoint.ViewPoint.X - 5,
                                            (float) calculatePoint.ViewPoint.Y - 10);
                RenderTarget.Transform = Matrix3x2F.Rotation(270, textPoint);
                RenderTarget.DrawTextLayout(textPoint, textlayout, _blackBrush);

                RenderTarget.Transform = Matrix3x2F.Rotation(0, textPoint);

                var triangleGeometry = Factory.CreatePathGeometry();
                using (var triangleSink = triangleGeometry.Open())
                {
                    triangleSink.BeginFigure(new Point2F((float) (calculatePoint.ViewPoint.X - 2.5f),
                                                         (float) calculatePoint.ViewPoint.Y - 7), FigureBegin.Filled);

                    triangleSink.AddLine(new Point2F((float) (calculatePoint.ViewPoint.X + 2.5f),
                                                     (float) calculatePoint.ViewPoint.Y - 7));
                    triangleSink.AddLine(new Point2F((float) calculatePoint.ViewPoint.X,
                                                     (float) (calculatePoint.ViewPoint.Y) - 2));
                    triangleSink.EndFigure(FigureEnd.Closed);
                    triangleSink.Close();
                }

                //RenderTarget.DrawGeometry(triangleGeometry, _blackBrush, 1);
                RenderTarget.FillGeometry(triangleGeometry, _redBrush);
            }

            // All done!
            RenderTarget.EndDraw();
        }
    }
}